package com.iplant.basic.serviceImpl.dao.bms;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.iplant.base.po.OutResult;
import com.iplant.base.po.Pagination;
import com.iplant.base.po.enums.ExceptionTypes;
import com.iplant.base.utils.general.StringUtils;
import com.iplant.base.utils.sql.BaseDAO;
import com.iplant.basic.service.po.bms.BMSDepartment;
import com.iplant.basic.service.po.bms.BMSEmployee;

public class BMSDepartmentDAO extends BaseDAO {
    private static BMSDepartmentDAO Instance = null;

    private BMSDepartmentDAO() {
        super();
        super.setTableName("bms_department");
    }

    private static Logger logger = LoggerFactory.getLogger(BMSDepartmentDAO.class);

    public static BMSDepartmentDAO getInstance() {
        if (Instance == null)
            Instance = new BMSDepartmentDAO();

        return Instance;
    }

    private BMSDepartment BMS_CheckDepartmentName(BMSEmployee wLoginUser, int wID, int wParentID, String wName,
                                                  OutResult<Integer> wErrorCode) {
        BMSDepartment wDepartment = new BMSDepartment();
        wErrorCode.set(0);
        try {

            Map<String, Object> wParams = new HashMap<String, Object>();
            String wSQLText = "";
            if (wID > 0) {
                wSQLText = StringUtils.Format(
                        "Select * from {0}.bms_department where ID!=:ID and Name=:Name and ParentID=:ParentID ;",
                        super.getDBName());

            } else {
                wSQLText = StringUtils.Format(
                        "Select * from {0}.bms_department where Name=:Name and ParentID=:ParentID;",
                        super.getDBName());

            }
            wParams.put("ID", wID);
            wParams.put("Name", wName);
            wParams.put("ParentID", wParentID);
            wSQLText = this.DMLChange(wSQLText);
            List<Map<String, Object>> wQueryResultList = super.queryForList(wSQLText, wParams);
            for (Map<String, Object> wSqlDataReader : wQueryResultList) {
                wDepartment.ID = StringUtils.parseInt(wSqlDataReader.get("ID"));
                wDepartment.Name = StringUtils.parseString(wSqlDataReader.get("Name"));
                wDepartment.Code = StringUtils.parseString(wSqlDataReader.get("Code"));
                wDepartment.Active = StringUtils.parseInt(wSqlDataReader.get("Active"));
                wDepartment.ParentID = StringUtils.parseInt(wSqlDataReader.get("ParentID"));
                wDepartment.Type = StringUtils.parseInt(wSqlDataReader.get("Type"));
                wDepartment.CreatorID = StringUtils.parseInt(wSqlDataReader.get("CreatorID"));
                wDepartment.EditorID = StringUtils.parseInt(wSqlDataReader.get("EditorID"));
                wDepartment.EditTime = StringUtils.parseCalendar(wSqlDataReader.get("EditTime"));
                wDepartment.CreateTime = StringUtils.parseCalendar(wSqlDataReader.get("CreateTime"));
                if (StringUtils.isEmpty(wDepartment.Code)) {
                    wDepartment.Code = StringUtils.Format("DEPT{0}", String.format("%06d", wDepartment.ID));
                }
            }

        } catch (Exception ex) {
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
            logger.error("BMS_CheckDepartmentName", ex);
        }
        return wDepartment;
    }

    public void BMS_AddDepartment(BMSEmployee wLoginUser, BMSDepartment wDepartment, OutResult<Integer> wErrorCode) {

        wErrorCode.set(0);

        try {

            BMSDepartment wDepartmentO = this.BMS_CheckDepartmentName(wLoginUser, 0, wDepartment.ParentID,
                    wDepartment.Name, wErrorCode);
            if (wDepartment.Name.length() < 1 || wDepartmentO.ID > 0) {
                wErrorCode.set(ExceptionTypes.Logic.getValue());
                return;
            }

            Map<String, Object> wParams = new HashMap<String, Object>();
            wParams.put("Name", wDepartment.Name);
            wParams.put("CreatorID", wLoginUser.getID());
            wParams.put("EditorID", wLoginUser.getID());
            wParams.put("EditTime", Calendar.getInstance());
            wParams.put("CreateTime", Calendar.getInstance());
            wParams.put("Active", wDepartment.Active);
            wParams.put("ParentID", wDepartment.ParentID);
            wParams.put("Description", wDepartment.Description);
            wParams.put("Type", wDepartment.Type);

            wParams.put("OrderNum", wDepartment.OrderNum);

            wDepartment.ID = super.Insert(StringUtils.Format("  {0}.bms_department", super.getDBName()),
                    wParams);

            if (StringUtils.isEmpty(wDepartment.Code)) {
                wDepartment.Code = StringUtils.Format("DEPT{0}", String.format("%06d", wDepartment.ID));
            }
        } catch (Exception ex) {
            logger.error("BMS_AddDepartment", ex);
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
        }
    }

    public void BMS_SaveDepartment(BMSEmployee wLoginUser, BMSDepartment wDepartment, OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);

        try {

            BMSDepartment wDepartmentO = this.BMS_CheckDepartmentName(wLoginUser, wDepartment.ID, wDepartment.ParentID,
                    wDepartment.Name, wErrorCode);
            if (wDepartment.Name.length() < 1 || wDepartmentO.ID > 0) {
                wErrorCode.set(ExceptionTypes.Logic.getValue());
                return;
            }

            Map<String, Object> wParams = new HashMap<String, Object>();
            String wSQLText = StringUtils.Format("Update {0}.bms_department", super.getDBName())
                    + " Set Code=:Code, Name=:Name,EditorID=:EditorID,OrderNum=:OrderNum,Description=:Description,"
                    + "EditTime=:EditTime,ParentID=:ParentID,Type=:Type,ManagerID=:ManagerID where ID=:ID  ;";

            wParams.put("Name", wDepartment.Name);

            wParams.put("EditorID", wLoginUser.getID());
            wParams.put("OrderNum", wDepartment.OrderNum);
            wParams.put("EditTime", Calendar.getInstance());
            wParams.put("ParentID", wDepartment.ParentID);
            wParams.put("Description", wDepartment.Description);
            wParams.put("ManagerID", StringUtils.Join(",", wDepartment.ManagerID));
            wParams.put("Type", wDepartment.Type);
            wParams.put("ID", wDepartment.ID);
            wParams.put("Code", StringUtils.Format("DEPT{0}", String.format("%06d", wDepartment.ID)));
            wSQLText = this.DMLChange(wSQLText);
            super.update(wSQLText, wParams);

        } catch (Exception ex) {
            logger.error("BMS_SaveDepartment", ex);
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
        }

    }

    public void BMS_DeleteDepartment(BMSEmployee wLoginUser, BMSDepartment wDepartment, OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);

        try {

            if (wDepartment == null || wDepartment.ID <= 0) {
                wErrorCode.set(ExceptionTypes.Parameter.getValue());
                return;
            }

            Map<String, Object> wParams = new HashMap<String, Object>();

            wParams.put("ID", wDepartment.ID);
            wParams.put("Active", 0);
            super.Delete(super.getTableName("bms_department"), wParams);

        } catch (Exception ex) {
            logger.error("BMS_DeleteDepartment", ex);
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
        }

    }

    public int BMS_ActiveDepartmentByID(BMSEmployee wLoginUser, int wID, OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);

        try {

            Map<String, Object> wParams = new HashMap<String, Object>();

            String wSQLText = StringUtils.Format("Update {0}.bms_department", super.getDBName())
                    + " Set  Code=:Code,EditorID=:EditorID,EditTime=:EditTime,Active=1 where ID=:ID";

            wParams.put("EditorID", wLoginUser.getID());
            wParams.put("EditTime", Calendar.getInstance());
            wParams.put("ID", wID);
            wParams.put("Code", StringUtils.Format("DEPT{0}", String.format("%06d", wID)));
            wSQLText = this.DMLChange(wSQLText);
            super.update(wSQLText, wParams);

        } catch (Exception ex) {
            logger.error("BMS_ActiveDepartmentByID", ex);
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
        }
        return wErrorCode.Result;
    }

    public int BMS_DisableDepartmentByID(BMSEmployee wLoginUser, int wID, OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);
        try {

            Map<String, Object> wParams = new HashMap<String, Object>();

            String wSQLText = StringUtils.Format("Update {0}.bms_department", super.getDBName())
                    + " Set Code=:Code, EditorID=:EditorID,EditTime=:EditTime,Active=2 where ID=:ID";

            wParams.put("EditorID", wLoginUser.getID());
            wParams.put("EditTime", Calendar.getInstance());
            wParams.put("ID", wID);
            wParams.put("Code", StringUtils.Format("DEPT{0}", String.format("%06d", wID)));
            wSQLText = this.DMLChange(wSQLText);
            super.update(wSQLText, wParams);

        } catch (Exception ex) {
            logger.error("BMS_DisableDepartmentByID", ex);
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
        }
        return wErrorCode.Result;
    }

    public List<BMSDepartment> BMS_QueryDepartmentList(BMSEmployee wLoginUser, int wParentID, String wName, int wType,
                                                       int wActive, Pagination wPagination,
                                                       OutResult<Integer> wErrorCode) {

        return this.BMS_QueryDepartmentList(wLoginUser, -1, "", wParentID, wName, wType, wActive, wPagination,
                wErrorCode);
    }

    private List<BMSDepartment> BMS_QueryDepartmentList(BMSEmployee wLoginUser, int wID, String wCode, int wParentID,
                                                        String wName, int wType, int wActive, Pagination wPagination,
                                                        OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);
        List<BMSDepartment> wDepartmentList = new ArrayList<BMSDepartment>();

        try {

            Map<String, Object> wParams = new HashMap<String, Object>();

            String wSQLText = StringUtils
                    .Format("Select t.*,t3.Name as CreatorName ,t4.Name as EditorName ,t5.Name as ParentName,"
                            + " group_concat(t2.Name) as ManagerName,count(t6.ID) as ItemCount from {0}" +
                            ".bms_department t "
                            + " left join {0}.mbs_user t3 on t.CreatorID=t3.ID "
                            + " left join {0}.mbs_user t4 on t.EditorID=t4.ID "
                            + " left join {0}.bms_department t5 on t.ParentID=t5.ID "
                            + " left join {0}.bms_department t6 on t6.ParentID=t.ID "
                            + " left join {0}.mbs_user t2 on  t2.Active=1 and find_in_set(t2.ID,t.ManagerID) "
                            + " where (:ID<=0 or  t.ID=:ID) and (:Code = '''' or  t.Code = :Code)"
                            + " AND (:Active<0 or  t.Active=:Active) AND (:ParentID<0 or  t.ParentID=:ParentID) "
                            + " AND (:Type<=0 or  t.Type=:Type) AND (:Name = '''' or  t.Name like :Name) "
                            + " group by t.ID", super.getDBName());
            wParams.put("ID", wID);
            wParams.put("Active", wActive);
            wParams.put("Code", wCode);
            wParams.put("Type", wType);
            wParams.put("ParentID", wParentID);
            wParams.put("Name", StringUtils.isEmpty(wName) ? "" : ("%" + wName + "%"));

            wSQLText = this.DMLChange(wSQLText);
            List<Map<String, Object>> wQueryResultList = super.queryForList(wSQLText, wParams, wPagination);
            for (Map<String, Object> wSqlDataReader : wQueryResultList) {
                BMSDepartment wDepartment = new BMSDepartment();
                wDepartment.ID = StringUtils.parseInt(wSqlDataReader.get("ID"));
                wDepartment.Name = StringUtils.parseString(wSqlDataReader.get("Name"));
                wDepartment.Code = StringUtils.parseString(wSqlDataReader.get("Code"));
                wDepartment.Active = StringUtils.parseInt(wSqlDataReader.get("Active"));
                wDepartment.ParentID = StringUtils.parseInt(wSqlDataReader.get("ParentID"));
                wDepartment.ParentName = StringUtils.parseString(wSqlDataReader.get("ParentName"));
                wDepartment.CreatorID = StringUtils.parseInt(wSqlDataReader.get("CreatorID"));
                wDepartment.EditorID = StringUtils.parseInt(wSqlDataReader.get("EditorID"));
                wDepartment.CreatorName = StringUtils.parseString(wSqlDataReader.get("CreatorName"));
                wDepartment.EditorName = StringUtils.parseString(wSqlDataReader.get("EditorName"));
                wDepartment.CreateTime = StringUtils.parseCalendar(wSqlDataReader.get("CreateTime"));
                wDepartment.EditTime = StringUtils.parseCalendar(wSqlDataReader.get("EditTime"));
                wDepartment.ManagerID = StringUtils.parseIntList(wSqlDataReader.get("ManagerID"), ",");
                wDepartment.ManagerName = StringUtils.parseString(wSqlDataReader.get("ManagerName"));
                wDepartment.Type = StringUtils.parseInt(wSqlDataReader.get("Type"));
                wDepartment.OrderNum = StringUtils.parseInt(wSqlDataReader.get("OrderNum"));
                wDepartment.ItemCount = StringUtils.parseInt(wSqlDataReader.get("ItemCount"));

                wDepartment.Description = StringUtils.parseString(wSqlDataReader.get("Description"));

                if (StringUtils.isEmpty(wDepartment.Code)) {
                    wDepartment.Code = StringUtils.Format("DEPT{0}", String.format("%06d", wDepartment.ID));
                }
                wDepartmentList.add(wDepartment);

            }
        } catch (Exception ex) {
            logger.error("BMS_QueryDepartmentList", ex);
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
        }
        return wDepartmentList;
    }

    public BMSDepartment BMS_QueryDepartmentByID(BMSEmployee wLoginUser, int wID, String wCode,
                                                 OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);
        BMSDepartment wResult = new BMSDepartment();

        try {

            List<BMSDepartment> wList = null;
            if (wID > 0) {
                wList = this.BMS_QueryDepartmentList(wLoginUser, wID, "", -1, "", -1, -1, Pagination.getDefault(),
                        wErrorCode);

            } else if (StringUtils.isNotEmpty(wCode)) {
                wList = this.BMS_QueryDepartmentList(wLoginUser, -1, wCode, -1, "", -1, -1, Pagination.getDefault(),
                        wErrorCode);
            }
            if (wList != null && wList.size() > 0) {
                wResult = wList.get(0);
            }

        } catch (Exception ex) {
            logger.error("BMS_QueryDepartmentByID", ex);
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
        }
        return wResult;
    }

    public List<BMSDepartment> BMS_QueryDepartmentListByID(BMSEmployee wLoginUser, int wID, String wCode,
                                                           OutResult<Integer> wErrorCode) {
        wErrorCode.set(0);
        List<BMSDepartment> wResult = new ArrayList<BMSDepartment>();

        try {

            if (wID > 0) {
                wCode = "";
            } else if (StringUtils.isNotEmpty(wCode)) {
                wID = -1;
            } else {
                return wResult;
            }

            List<BMSDepartment> wList = this.BMS_QueryDepartmentList(wLoginUser, -1, "", -1, "", -1, -1,
                    Pagination.getMaxSize(), wErrorCode);

            for (BMSDepartment bmsDepartment : wList) {
                if (bmsDepartment.ID == wID || bmsDepartment.Code.equals(wCode)) {
                    wResult.add(bmsDepartment);

                    break;
                }
            }

            if (wResult.size() > 0) {

                this.BMS_SetParentDepartment(wLoginUser, wList, wList.get(wList.size() - 1).ParentID, wResult);
            }

        } catch (Exception ex) {
            logger.error("BMS_QueryDepartmentByID", ex);
            wErrorCode.set(ExceptionTypes.DBSQL.getValue());
        }
        return wResult;
    }

    private void BMS_SetParentDepartment(BMSEmployee wLoginUser, List<BMSDepartment> wSourceList, int wParentID,
                                         List<BMSDepartment> wResult) {

        if (wSourceList == null || wResult == null || wParentID <= 0)
            return;

        boolean wIsOwn = false;
        for (BMSDepartment bmsDepartment : wResult) {

            if (bmsDepartment.ID == wParentID) {

                wResult.add(bmsDepartment);
                wIsOwn = true;
                break;
            }
        }
        if (wIsOwn) {
            this.BMS_SetParentDepartment(wLoginUser, wSourceList, wSourceList.get(wSourceList.size() - 1).ParentID,
                    wResult);
        }

    }
}
